package com.neuedu.service.impl;

import com.auth0.jwt.JWT;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.neuedu.pojo.Mail;
import com.neuedu.pojo.User;
import com.neuedu.mapper.UserMapper;
import com.neuedu.service.IMailService;
import com.neuedu.service.IRedisService;
import com.neuedu.service.IUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.neuedu.util.JWTUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.*;

/**
 * <p>
 * 用户 服务实现类
 * </p>
 *
 * @author wgq
 * @since 2020-09-18
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
    @Resource
    BCryptPasswordEncoder bCryptPasswordEncoder;

    @Resource
    IRedisService redisService;

    @Resource
    IMailService mailService;


    @Override
    public String token(User user) throws JsonProcessingException {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        //根据用户名查询 用户对象
        wrapper.eq("username", user.getUsername());
        User queryUser = this.getOne(wrapper);
        if (queryUser != null) {
            //如果用户名存在则验证密码
            //如果密码一致则认为登录成功
            if (bCryptPasswordEncoder.matches(user.getPassword(), queryUser.getPassword())) {
                //将用户信息生成token数据返回给前端

                LocalDateTime now = LocalDateTime.now();
                queryUser.setLastLogin(now);
                String token = JWTUtil.create(queryUser);

                //保存登录状态信息 --》 ssdb
                //umsuser-admin

                updateLastLogin(queryUser.getId(), now);

                //缓存用户登录信息
                write2SSDB(queryUser, now);

                return token;
            }
        }

        return null;
    }

    private void write2SSDB(User user, LocalDateTime now) throws JsonProcessingException {
        Map info = new HashMap<>();
        info.put("username", user.getUsername());
        info.put("password", user.getPassword());
        info.put("id", user.getId());
        info.put("lastLogin", now.toInstant(ZoneOffset.of("+8")).toEpochMilli());

        ObjectMapper objectMapper = new ObjectMapper();
        String key = JWTUtil.KEY + "-" + user.getUsername();
        String userJson = objectMapper.writeValueAsString(info);

        redisService.set(key, userJson, 60 * 30);
    }

    /**
     * 更新最后登录成功的时间
     *
     * @param id
     * @param now
     */
    private void updateLastLogin(Integer id, LocalDateTime now) {
        User user = new User();
        user.setId(id);
        user.setLastLogin(now);
        updateById(user);
    }

    @Override
    public Object list(User umsUser) {
        // 如果 有name传过来 就按照name 模糊查询
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        if (StringUtils.isNotBlank(umsUser.getUsername())) {
            wrapper.like("username", umsUser.getUsername());
        }
        if (umsUser.getActive() != null) {
            wrapper.eq("active", umsUser.getActive());
        }

        // 如果分页返回 IPage 如果不分页 返回 List
        if (umsUser.getWithPage() == 1) {
            return this.page(new Page<>(umsUser.getPageNo(), umsUser.getPageSize()), wrapper);
        } else {
            return this.list(wrapper);
        }

    }

    @Override
    public boolean add(User umsUser) {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("username", umsUser.getUsername());
        User query = this.getOne(wrapper);
        if (query == null)
            return this.save(umsUser);
        return false;
    }

    @Override
    public boolean batchDel(Integer[] ids) {
        List<Integer> list = new ArrayList<>(ids.length);
        Collections.addAll(list, ids);
        User user = new User();
        user.setActive(0);
        UpdateWrapper<User> wrapper = new UpdateWrapper<>();
        wrapper.in("id", list);
        return this.update(user, wrapper);
    }

    @Override
    public boolean logout(HttpServletRequest request) {
        String token = request.getHeader("token");
        String username = JWT.decode(token).getClaim("username").asString();
        //删除key
        String key = JWTUtil.KEY + "-" + username;

        //设置有效期为0
        redisService.expire(key, 0);

        return true;
    }

    @Override
    public User currentUser(HttpServletRequest request) {
        String token = request.getHeader("token");
        String username = JWT.decode(token).getClaim("username").asString();
        QueryWrapper wrapper = new QueryWrapper();
        wrapper.eq("username", username);
        return this.getOne(wrapper);
    }

    @Override
    public boolean changePassword(String username, String securityCode, String password) {
        String sc = redisService.get(JWTUtil.SECURITYCODE_KEY + "-" + username);
        if (sc == null || !sc.equals(securityCode)) {
            return false;
        } else {
            QueryWrapper<User> wrapper = new QueryWrapper<>();
            wrapper.eq("username", username);
            User user = this.getOne(wrapper);
            user.setPassword(bCryptPasswordEncoder.encode(password));
            this.saveOrUpdate(user);
            redisService.expire(JWTUtil.SECURITYCODE_KEY + "-" + username, 0);
            return true;
        }
    }
}
